#!/bin/bash

VERSION="1.1.8"

info() {
    echo -e "\033[32m[Info]\033[0m $1"
}

error() {
    echo -e "\033[31m[Error]\033[0m $1"
}

red() {
    echo -e "\033[31m$1\033[0m"
}

yellow() {
    echo -e "\033[0;33m$1\033[0m"
}

blue() {
    echo -e "\033[0;34m$1\033[0m"
}

# 检测系统类型
check_sys() {
    if [ -f /etc/alpine-release ]; then
        OS="alpine"
    elif [ -f /etc/debian_version ]; then
        OS="debian"
    elif [ -f /etc/redhat-release ]; then
        OS="centos"
    else
        OS="unknown"
    fi
}

# 安装基础依赖
install_base_packages() {
    case $OS in
        alpine)
            apk update
            apk add --no-cache wget unzip curl jq tzdata nftables
            ;;
        debian)
            sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
            apt update -y
            apt install -y wget unzip curl jq tzdata nftables
            ;;
        centos)
            yum install -y wget unzip curl jq tzdata nftables
            ;;
    esac
}

config_system(){
    check_sys
    install_base_packages

    # 配置时区
    case $OS in
        alpine)
            cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
            echo "Asia/Shanghai" > /etc/timezone
            ;;
        *)
            cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
            echo "Asia/Shanghai" > /etc/timezone
            ;;
    esac

    # DNS配置（针对systemd系统）
    if [ -d /etc/systemd ]; then
        cat >>/etc/systemd/resolved.conf <<-EOF
DNSStubListener=no
EOF
    fi

    # 系统参数配置
    cat >/etc/sysctl.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1

net.core.default_qdisc = fq_pie
net.ipv4.tcp_congestion_control = bbr

net.ipv4.ip_local_port_range = 1024 65535

net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_max_syn_backlog = 4096
net.core.somaxconn = 4096
net.ipv4.tcp_abort_on_overflow = 1

net.ipv4.tcp_slow_start_after_idle = 0

fs.file-max = 6553560
EOF
    sysctl -p
}

install_smbox(){
    nft flush ruleset
    arch=$(uname -m)
    if [ "$arch" == "x86_64" ]; then
        arch="amd64"
    fi

    if [ "$arch" == "aarch64" ]; then
        arch="arm64"
    fi

    link=http://154.17.224.29/public/smbox/smbox-${arch}.zip
    wget "$link" -O smbox.zip
    if [ -f sbdir/cache.db ]; then
        cp sbdir/cache.db /tmp/singbox/cache.db
        cp -r sbdir/ui /tmp/singbox/ui
    fi
    unzip -o smbox.zip
    if [ -f /tmp/singbox/cache.db ]; then
        cp /tmp/singbox/cache.db sbdir/cache.db
    fi
    if [ -d /tmp/singbox/ui ]; then
        cp -r /tmp/singbox/ui sbdir/ui
    fi
    ./smbox install
    rm -f smbox.zip
    rm -f /tmp/cache.db
}

install_smbox_dev(){
    nft flush ruleset
    arch=$(uname -m)
    if [ "$arch" == "x86_64" ]; then
        arch="amd64"
    fi

    if [ "$arch" == "aarch64" ]; then
        arch="arm64"
    fi

    link=http://154.17.224.29/public/smbox/smbox-${arch}-beta.zip
    wget "$link" -O smbox.zip
    if [ -f sbdir/cache.db ]; then
        cp sbdir/cache.db /tmp/cache.db
    fi
    unzip -o smbox.zip
    if [ -f /tmp/cache.db ]; then
        cp /tmp/cache.db sbdir/cache.db
    fi
    ./smbox install
    rm -f smbox.zip
    rm -f /tmp/cache.db
}

downloadYACD() {
    rm -rf /root/sbdir/ui/*
    wget https://github.com/MetaCubeX/yacd/archive/gh-pages.zip -O yacd.zip
    unzip yacd.zip
    mv Yacd-meta-gh-pages/* /root/sbdir/ui/
    rm -rf Yacd-meta-gh-pages
    rm -f yacd.zip
}

downloadMetaUI() {
    check_sys
    install_base_packages
    
    prereleaseStatus=false
    version=$(curl -s "http://154.17.224.29/rproxy?url=https://api.github.com/repos/MetaCubeX/metacubexd/releases?per_page=20" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
    wget https://github.com/MetaCubeX/metacubexd/releases/download/${version}/compressed-dist.tgz -O compressed-dist.tgz
    rm -rf /root/sbdir/ui/*
    tar -zxvf compressed-dist.tgz -C /root/sbdir/ui/
    rm -f compressed-dist.tgz
}

downloadSingBox() {
    arch=$1
    check_sys
    install_base_packages

    prereleaseStatus=false
    version=$(curl -s "http://154.17.224.29/rproxy?url=https://api.github.com/repos/SagerNet/sing-box/releases?per_page=20" | jq -r ".[]|select (.prerelease==${prereleaseStatus})|.tag_name" | head -1)
    info "Downloading SingBox"
    file_name=sing-box-${version/v/}-linux-${arch}

    tar_name=${file_name}.tar.gz
    wget http://154.17.224.29/rproxy?url=https://github.com/SagerNet/sing-box/releases/download/${version}/${tar_name} -O $tar_name
    tar -zxvf ${tar_name}
    mv ${file_name}/sing-box /root/sbdir/singbox
    chmod +x /root/sbdir/singbox
    blue "sb upgrade success"
    ./smbox restart
    rm -f ${tar_name}
}

uninstall() {
    ./smbox stop
    ./smbox uninstall
    rm -rf ./sbdir
    rm -rf ./mosdns
    rm -rf ./logs
    rm -rf ./config
    rm -rf ./web
    rm -f ./smbox
    rm -f ./manage.sh
    rm -f /etc/nftables.conf
    nft flush ruleset
    info "卸载成功"
}

reset(){
    ./smbox stop
    rm -rf ./config
    rm -rf ./logs
    ./smbox start
    nft flush ruleset
    info "重置成功"
}

get_host_ip() {
    host_ip=$(ip addr show $(ip route show default | awk '/default/ {print $5}') | awk '/inet / {print $2}' | cut -d/ -f1)
    echo $host_ip
}

show_menu() {
    yellow "1. 安装SMbox"
    yellow "2. 升级SMbox"
    yellow "3. 安装SMbox测试版"
    yellow "4. 升级SMbox测试版"
    yellow "5. 卸载SMbox"
    yellow "6. 重置SMbox"
    red "0. exit"
    read -p "输入操作: " num
    case $num in
    1)
        config_system
        install_smbox
        blue "安装完成"
        yellow "请用浏览器打开 http://$(get_host_ip)"
        blue "默认用户名: admin"
        blue "默认密码: admin"
        ;;
    2)
        ./smbox uninstall
        install_smbox
        blue "升级完成"
        yellow "请用浏览器打开 http://$(get_host_ip)"
        ;;
    3)
        config_system
        install_smbox_dev
        blue "安装完成"
        yellow "请用浏览器打开 http://$(get_host_ip)"
        blue "默认用户名: admin"
        blue "默认密码: admin"
        ;;
    4)
        ./smbox uninstall
        install_smbox_dev
        blue "升级完成"
        ;;
    5)
        uninstall
        ;;
    6)
        reset
        ;;
    0)
        exit 0
        ;;
    esac
}

show_menu
